test

5.3 确定测试目标

基准测试的测试目标取决于目标应用程序的具体类型,需要依实际情况来确定。

5.3.1 吞吐量

测试以吞吐量为优化目标的应用程序相对来说会容易一些,测试时需要注意的是在给定的周期内尽可能多的执行应用程序的具体操作。作为回归测试使用时,基准测试需要验证,在基线硬件(baselined hardware)上,应用程序是否仍旧可以在y秒内执行x个操作。如果满足条件的话,就可以继续测试是否可以维持住吞吐量。

正如在3.3.5.1节中提到的,吞吐量本身通常不是什么大问题(除非是批处理任务和离线分析场景下),写一个用来测试吞吐量的基准测试也不是什么难事,通常可以直接从主应用程序中直接抽取出来,根本无需使用什么技巧。

5.3.2 兼顾吞吐量、响应时间和延迟

通常可以对前面提到的以吞吐量为目标的基准测试进行改进,使其可用于测量在给定的响应时间范围内的吞吐量。

如果为基准测限制了固定的响应时间,那么也就加上了延迟这个限制因素。该基准测试可用来验证应用程序在预设的响应时间范围内,是否可以稳定运行于不同的工作负载下。

JRockit质量保证团队内部使用基准测试套件中包含了很多附加了响应时间要求的吞吐量基准测试工具。这些工具用来验证准确式垃圾回收器在不同的工作负载下是否可以满足任务需要。

对大多数用户来说,低延迟通常比高吞吐更重要,至少在C/S架构的程序中是这样的,而编写以低延迟为目标的基准测试会更具挑战。

一般情况下,简单的Web应用程序的响应时间会在1秒左右,而在金融行业,普遍要求应用程序暂停时间要小于10毫秒。

类似的,在电信行业,通常要求应用程序的暂停时间要小于50毫秒。为了满足这些要求,用户和JVM厂商就需要针对低延迟要求做细致的基准测试。

5.3.3 伸缩性

针对伸缩性进行的基准测试主要是测量相关资源的利用率。良好的伸缩性意味着随着工作负载的上升,应用程序依然运行稳定,标签良好。如果应用程序的伸缩性不好,说明其无法充分利用硬件资源,结果往往会导致吞吐量下降。理想情况下,线性增长的工作负载最多只会使应用程序的性能和服务质量现行下降。

下图是每个CPU核心上伸缩性呈近似线性变化的例子,其中吞吐量是通过在老版本JRockit JVM上运行SPECjbb2005基准测试得出的。SPECjbb2005是一个多线程基准测试程序,其会在一个事务处理框架中逐步增大工作负载。

Figure 4-9

SPECjbb在进行基准测试时一开始使用的工作线程数会少于CPU核心数,然后随着测试的进行而增加工作线程的数量,进而增大应用程序的吞吐量。有点像增量式热身。从上图中可以看出,开始的时候,增加工作线程数使目标应用程序的吞吐量呈线性增长,直到工作线程的数量等于CPU核心数,这时吞吐量已成饱和状态。此后,再继续增加工作线程数,吞吐量也不会继续呈线性提升了,而是保持在某一水平直到测试结束。这就是说,该应用程序在伸缩性方面做的不错。5.4.1节中会对SPECjbb做详细介绍。

就上面的测试结果来说,目标应用程序在指定JVM具有不错的伸缩性。简单来说就是,如果数据量增大。只需要增加更多的硬件设备就可以了。保持伸缩性涉及到应用程序层面的算法实现,以及JVM和操作系统层面如何应对新增的工作负载,具体包括网络拥堵、CPU周期,以及并行执行的线程等。

具有良好的伸缩性是最理想的状态,作为一个优化目标,它意味着应用程序是否可以充分发挥出硬件的潜能。某些对伸缩性的优化是基于理论上具有上千个CPU核心的机器所做的,从实践应用来看,这些优化可能只是无用功而已,对整体伸缩性的过分追求反而可能会使其成为造成小应用程序性能低下的主要原因。

5.3.4 能源消耗

以往常常被忽视的能源消耗测试现在正变得越来越重要。能源消耗的重要性不仅仅体现在嵌入式领域,当服务器集群足够大时,能源消耗也将成为重要的影响因素。由于存在冷却成本和服务器基础架构等问题,能源消耗愈发凸显其重要性,因为它直接关系到数据中心所需空间的大小。针对于此,为了能从现在有硬件中获得更大收益,业界已广泛采用虚拟化技术,但即便如此,在应用程序层面对能源消耗做基准测试也还是很有必要的。

降低应用程序的能源消耗会涉及到多方面内容,例如用操作系统线程的锁替换自旋锁以节省CPU消耗,或者减少操作系统和应用程序之间的数据转移等等。

对此,一个颇具主动性的解决办法是,在开发阶段想办法使应用程序在低主频的CPU上,或者只使用部分CPU核心时,也能满足性能要求。

5.3.5 其他方面

当然,在对应用程序的性能做基准测试时,还有一些其他方面的问题需要考虑,需要根据应用程序自身的特点做详细分析。有时候,光是确定"性能"的含义就足够让人头疼了。